/*******************************************************
*文件名：tammager.cpp
*创建人：buptsoft团队
*创建日期：2014/3/15
*修改人：
*日期:
*描述：包含了一个用于文件处理的类Tmamager
*版本：v0.0.5 buptsoftCopyright(c).
********************************************************/
#ifndef _INC_TMANAGER
#define _INC_TMANAGER
#include <stdio.h>
#include<iostream>
#include<fstream>
#include<conio.h>
#include<stdlib.h>
using namespace std;
typedef struct filelink{
    char* text;
    struct filelink* last;
    struct filelink* next;
}Filelink;
typedef struct result{
    Filelink * left;
    Filelink * right;
}Res;
class Tmanager{
public:
    Filelink* headF;
    Filelink* note;//光标处
    Res res;
private:
    fstream Fstream;
    char ch;
    int i,count;
    Filelink* curF;
    Filelink* newF;

    /**
        the next part is uesd to restore the result of the search
    */
    Filelink* buffer;
public:
/*******************************************************
*函数名：Tmanager()
*功能:对Tmanager类中的所有变量初始化，并且根据传入的文件
*	  名向内存中读入文件。
*返回值：无返回值
*参数：char* string 为打开的文件名
*备注：该函数在初始化时必须调用
********************************************************/
    Tmanager(char*string){
        printf("initstart");
        i=0;
        count=0;
        headF=NULL;
        curF=NULL;
        newF=NULL;
        //countF=NULL;
        note=NULL;
        buffer=NULL;
        res.left=NULL;
        res.right=NULL;
        Fstream.open(string);
        while(!Fstream.eof()){
        if(headF==NULL){
            headF=(Filelink*)malloc(sizeof(Filelink));
            headF->text=(char*)malloc(3*sizeof(char));
            for(int i=0;i<=2;i++)headF->text[i]=0;
            curF=headF;
            curF->last=NULL;
            curF->next=NULL;
            //Fstream.read(curF->text,1);
            //if(check(curF->text))Fstream.read(&curF->text[1],1);
        }
        else {
            newF=(Filelink*)malloc(sizeof(Filelink));
            newF->last=curF;
            newF->next=NULL;
            curF->next=newF;
            curF=newF;
            curF->text=(char*)malloc(3*sizeof(char));
            for(int i=0;i<=2;i++)curF->text[i]=0;
            Fstream.read(curF->text,1);
            if(check(curF->text))
                Fstream.read(&curF->text[1],1);
        }

    }
        note=headF;
        printf("initend");
        Fstream.close();
    }
/*******************************************************
*函数名：save()
*功能:向指定文件中保存内存中的数据
*返回值：无返回值
*参数：无传入参数
*备注：是否save由程序或用户决定
********************************************************/
    void save(char* string){
        ofstream sf;
        sf.open(string);
        for(Filelink * ff=headF;ff!=NULL;ff=ff->next){
            if(ff&&ff->text){
                sf<<ff->text;
            }
        }
        sf.close();
    }
/*******************************************************
*函数名：copy()
*功能:从键盘读入一组字符串，并且保存在buffer中
*返回值：无返回值
*参数：无传入参数
*备注：这是一个win32控制台下读取字符串的通用函数，输入的
*		字符串以空格结束，并且保存在buffer（Filelink*）中
********************************************************/
    void copy(){
        if(res.left&&res.right){
            Filelink * TEMPLINK=res.left,*TEMP_OLD=NULL,*TEMP_NEW=NULL;
            buffer=NULL;
            TEMP_NEW=(Filelink*)malloc(sizeof(Filelink));
            TEMP_NEW->last=NULL;
            TEMP_NEW->text=(char*)malloc(3*sizeof(char));
            for(int i=0;i<3;i++)
                TEMP_NEW->text[i]=TEMPLINK->text[i];
            TEMP_NEW->next=NULL;
            buffer=TEMP_NEW;
            TEMPLINK=TEMPLINK->next;
            for(;TEMPLINK&&((!res.right->next&&TEMPLINK!=res.right)||TEMPLINK!=res.right->next)&&TEMPLINK->next;TEMPLINK=TEMPLINK->next){
                TEMP_OLD=TEMP_NEW;
                TEMP_NEW=(Filelink*)malloc(sizeof(Filelink));
                TEMP_NEW->last=TEMP_OLD;
                TEMP_NEW->text=(char*)malloc(3*sizeof(char));
                for(int i=0;i<3;i++)
                    TEMP_NEW->text[i]=TEMPLINK->text[i];
                TEMP_NEW->next=NULL;
                TEMP_OLD->next=TEMP_NEW;
            }
        }
    }
/*******************************************************
*函数名：cut()
*功能:从键盘读入一组字符串，并且保存在buffer中
*返回值：无返回值
*参数：无传入参数
*备注：这是一个win32控制台下读取字符串的通用函数，输入的
*		字符串以空格结束，并且保存在buffer（Filelink*）中
********************************************************/
    void cut(){
        if(res.left&&res.right&&res.left->last){
            note=res.left->last;
            buffer=res.left;
            res.left->last->next=res.right->next;
            res.right->next->last=res.left->last;
            res.right->next=NULL;
            res.left=NULL;
            res.right=NULL;
        }
    }
/*******************************************************
*函数名：paste()
*功能:从键盘读入一组字符串，并且保存在buffer中
*返回值：无返回值
*参数：无传入参数
*备注：这是一个win32控制台下读取字符串的通用函数，输入的
*		字符串以空格结束，并且保存在buffer（Filelink*）中
********************************************************/
    void paste(){
        if(note&&buffer){
            Filelink * TEMP=NULL;
            Filelink * TEMP_NEW=NULL;
            Filelink * TEMP_OLD=NULL;
            Filelink * TEMP_BUFFER=buffer;
            TEMP_NEW=(Filelink*)malloc(sizeof(Filelink));
            TEMP_NEW->last=NULL;
            TEMP_NEW->text=(char*)malloc(3*sizeof(char));
            for(int i=0;i<3;i++)TEMP_NEW->text[i]=TEMP_BUFFER->text[i];
            TEMP_NEW->next=NULL;
            TEMP_BUFFER=TEMP_BUFFER->next;
            TEMP=TEMP_NEW;
            for(;TEMP_BUFFER;TEMP_BUFFER=TEMP_BUFFER->next){
                TEMP_OLD=TEMP_NEW;
                TEMP_NEW=(Filelink*)malloc(sizeof(Filelink));
                TEMP_NEW->last=TEMP_OLD;
                TEMP_NEW->text=(char*)malloc(3*sizeof(char));
                for(int i=0;i<3;i++)TEMP_NEW->text[i]=TEMP_BUFFER->text[i];
                TEMP_NEW->next=NULL;
                TEMP_OLD->next=TEMP_NEW;
            }
            Filelink * TEMP_HEAD_L=note;
            Filelink * TEMP_HEAD_R=TEMP;
            Filelink * TEMP_TAIL_L=NULL;
            Filelink * TEMP_TAIL_R=note->next;
            for(TEMP_TAIL_L=TEMP;TEMP_TAIL_L&&TEMP_TAIL_L->next;TEMP_TAIL_L=TEMP_TAIL_L->next);
            TEMP_HEAD_L->next=TEMP_HEAD_R;
            TEMP_HEAD_R->last=TEMP_HEAD_L;
            TEMP_TAIL_L->next=TEMP_TAIL_R;
            TEMP_TAIL_R->last=TEMP_TAIL_L;
            //buffer=NULL;
            res.left=TEMP_HEAD_R;
            res.right=TEMP_TAIL_L;
            note=NULL;
        }
    }
    bool buffer_exist(){
        if(buffer)
            return 1;
        else
            return 0;
    }
    Filelink * return_buffer(){
        return buffer;
    }
/*******************************************************
*函数名：Delete（）
*功能:在光标处向前删除一个节点
*返回值：无返回值
*参数：无
*备注：若光标指针note为空则不进行任何操作
********************************************************/
    void Delete(){
        if(!(res.left&&res.right)){
        if(note&& note!=headF){
            Filelink * buffer=note;
            if(note->text)
                free(note->text);
            if(headF->next==note){
                headF->next=note->next;
                if(note->next)
                    note->next->last=headF;
                note=headF;//note=note->next;
            }else{
                if(note->last)
                    note->last->next=note->next;
                if(note->next)
                    note->next->last=note->last;
                note=note->last;
            }
            free(buffer);
        }
        }else{
            Filelink* onDeletel=res.left->last,*onDeleter=res.right,*delbuf=res.left;
            note=res.left->last;
            res.left=NULL;
            res.right=NULL;
            while(delbuf!=onDeleter){
                delbuf=delbuf->next;
                free(delbuf->last->text);
                free(delbuf->last);
            }
            onDeletel->next=onDeleter->next;
            if(onDeleter->next)
                onDeleter->next->last=onDeletel;
        }
    }
/*******************************************************
*函数名：Cancel（）
*功能:在光标处向后删除一个节点
*返回值：无返回值
*参数：无
*备注：若光标指针note为空则不进行任何操作
********************************************************/
void Cancel(){
        if(note&&note->next)
            note=note->next;
        if(!(res.left&&res.right)){
        if(note&& note->next){
            Filelink * buffer=note;
            if(note->text)
                free(note->text);
            if(headF==note){
                headF=note->next;
                if(note->next)
                    note->next->last=NULL;
                note=headF;//note=note->next;
            }else{
                if(note->last)
                    note->last->next=note->next;
                if(note->next)
                    note->next->last=note->last;
                note=note->next;
            }
            free(buffer);
        }
        }else{
            Filelink* onDeletel=res.left->last,*onDeleter=res.right,*delbuf=res.left;
            note=res.left->last;
            res.left=NULL;
            res.right=NULL;
            while(delbuf!=onDeleter){
                delbuf=delbuf->next;
                free(delbuf->last->text);
                free(delbuf->last);
            }
            onDeletel->next=onDeleter->next;
            if(onDeleter->next)
                onDeleter->next->last=onDeletel;
            if(note->next)note=note->next;
        }
        if(note&&note->last)
            note=note->last;
    }
/*******************************************************
*函数名：Insert()
*功能:在光标指针后插入一个新的节点
*返回值：无返回值
*参数：无
*备注：无
********************************************************/
    void Insert(char* str,int job=0){
        Filelink* countF;
        if(note!=NULL){
            countF=(Filelink*)malloc(sizeof(Filelink));
            countF->last=note;
            countF->next=note->next;
            if(note->next)
            note->next->last=countF;
            note->next=countF;
            note=note->next;
            countF->text=str;
            if(job==1)
                res.left=countF,res.right=countF;
            else if(job==2)
                res.right=countF;
        }
    }
/*******************************************************
*函数名：search()
*功能:在文件中对传入的链表进行搜索
*返回值：返回值若为true则搜索成功，反则搜索失败
*参数：Filelink* input 为传入的要搜索的字符串链表
*备注：搜索结果储存在res中res为一个Res的结构体，专门用于
*	   存放块数据的指针
********************************************************/
    bool search(Filelink* input){
        if(input&&input->text){
             Filelink* l=note,* r=note,* n=input;
             if(!l)
                 l=res.right?res.right->next:NULL;
             if(!l)
                 l=headF->next;
             note=NULL;
             while(l!=NULL){
                 r=l;
                 n=input;

                 while(n&&n->text&&r&&r->text){
                     if(equals(n,r)){
                        if(!n->next->next){
                            res.left=l;
                            res.right=r;
                            return true;
                        }
                     }else
                        break;
                    n=n->next;
                    r=r->next;
                 }
                 l=l->next;
             }

        }
        return false;
    }
/*******************************************************
*函数名：equals()
*功能:判断两个Filelink中的第一个文字是否相同
*返回值：true为相同，反则为不相同
*参数：a,b,为Filelink*型
*备注：仅比较第一个字符，支持中文
********************************************************/
    bool equals(Filelink* a,Filelink* b){
        if(a&&b&&a->text&&b->text){
            for(int i=0;i<3;i++)
                if(a->text[i]!=b->text[i])
                    return false;
                return true;
        }else
        return false;
    }
    /*******************************************************
    *函数名：note_move_right();
    *功能:将光标向右移动
    *返回值：无
    *参数：无
    *备注：无
    ********************************************************/
    void note_move_right(){
        if(res.left&&res.right){
            note=res.right;
            res.left=NULL;
            res.right=NULL;
        }
        else if(note&&note->next->next)
            note=note->next;
    }
    /*******************************************************
    *函数名：note_move_left();
    *功能:将光标向左移动
    *返回值：无
    *参数：无
    *备注：无
    ********************************************************/
    void note_move_left(){
        if(res.left&&res.right){
            note=res.left->last;
            res.left=NULL;
            res.right=NULL;
        }
        else if(note&&note->last)
            note=note->last;
    }
    /*******************************************************
    *函数名：res_check();
    *功能:判断res是否错序,若错序置空
    *返回值：错序返回true，否则返回false
    *参数：无
    *备注：无
    ********************************************************/
    bool res_check(){
        if(res.left&& res.right){
            Filelink  *TEMPLINK=res.left;
            for(;TEMPLINK->next!=NULL;TEMPLINK=TEMPLINK->next)
                if(TEMPLINK==res.right){
                    return false;
                }
            for(TEMPLINK=res.right;TEMPLINK->next!=NULL;TEMPLINK=TEMPLINK->next)
                if(TEMPLINK==res.left){
                    res.left=res.right;
                    res.right=TEMPLINK;
                    return true;
                }
            res.left=NULL;
            res.right=NULL;
            return true;
        }
        else
            return true;
    }
private:
/*******************************************************
*函数名：check()
*功能:对中文的的支持，若是中文
*返回值：若数组中第一个字为中文则返回true，反则返回false
*参数：char* a 为要判断的数组
*备注：外部不可调用
********************************************************/
    bool check(char*a){
        int i=0,count=0;
        for(;a[i]<0&&i>=0;i--)count++;
        if(count%2==1)return true;
        else return false;
    }
/*******************************************************
*函数名：print_f()
*功能:将Filelink中的数据打印在win32控制台上
*返回值：无返回值
*参数：Filelink* f为要打印的链表
*备注：仅在调试时使用
********************************************************/
    void print_f(Filelink* f){

        printf("\nbegins:");
        Filelink* t=f;
        while(t!=NULL){
            if(t->text)printf("%s",t->text);
            t=t->next;
        }
        printf("ends");
    }
};
#endif
